// 实现标记重复记录的脚本插件（v2版本）
// 该脚本会根据用户输入的多个标识字段的值来识别重复记录，并使用比较字段来决定标记方式
// 运行脚本后，会创建一个新字段用来标记重复记录

async function main() {
  try {
    // 使用表单方式获取用户输入配置
    const formResult = await Input.formAsync('标记重复记录配置', [
      {
        type: 'sheet',
        key: 'sheet',
        option: {
          label: '数据表',
          description: '请选择要操作的数据表'
        },
        required: true
      },
      {
        type: 'text',
        key: 'idFieldsInput',
        option: {
          label: '标识字段',
          description: '请输入标识字段（多个字段用逗号分隔）'
        },
        required: true
      },
      {
        type: 'select',
        key: 'markType',
        option: {
          label: '标记方式',
          description: '请选择重复记录的标记方式',
          options: ['标记全部', '首项不标记', '末项不标记']
        },
        required: true
      },
      {
        type: 'field',
        key: 'comparisonField',
        option: {
          label: '比较字段',
          description: '请选择用于排序的比较字段（标记全部时可不选）',
          referenceSheet: 'sheet'
        },
        required: false
      }
    ]);
    
    const sheet = formResult.sheet;
    const idFieldsInput = formResult.idFieldsInput;
    const idFields = idFieldsInput.split(/,|，/g).map(field => field.trim());
    
    const markType = formResult.markType;
    const comparisonField = formResult.comparisonField;
    
    // 验证标识字段是否存在
    const sheetFields = sheet.getFields();
    const fieldNames = sheetFields.map(field => field.getName());
    const fieldIds = sheetFields.map(field => field.getId());
    const validFields = [...fieldNames, ...fieldIds];
    Output.log(fieldIds);
    Output.log(validFields);
    const invalidFields = idFields.filter(field => !validFields.includes(field));
    if (invalidFields.length > 0) {
      Output.error(`以下标识字段不存在: ${invalidFields.join(', ')}`);
      return;
    }
    
    // 验证标记方式和比较字段的组合
    if (markType !== '标记全部' && !comparisonField) {
      Output.error('当标记方式为"首项不标记"或"末项不标记"时，比较字段是必填项');
      return;
    }
    
    // 多维表限制批量操作最多50条记录
    const maxRecordsPerCall = 50;
    
    // 检查是否已存在"标记重复值"字段
    let duplicateFlagField = sheet.getField('标记重复值');
    let duplicateFlagFieldId;
    
    if (duplicateFlagField) {
      // 如果字段已存在，询问用户是否覆盖
      const overwrite = await Input.selectAsync('字段"标记重复值"已存在，是否覆盖该字段值?', ['是', '否']);
      if (overwrite === '否') {
        Output.log('用户取消操作');
        return;
      }
      duplicateFlagFieldId = duplicateFlagField.getId();
    } else {
      // 创建用于标记重复记录的新字段
      duplicateFlagField = sheet.insertField({ name: '标记重复值', type: 'text' });
      duplicateFlagFieldId = duplicateFlagField.getId();
    }
    
    // 获取所有记录，最多处理20000条
    const allRecords = [];
    let hasMore = true;
    let cursor = "";
    const maxRecords = 20000;

    while (hasMore && allRecords.length < maxRecords) {
      const result = await sheet.getRecordsAsync({
        pageSize: 100,
        cursor: cursor,
      });
      Output.log(JSON.stringify(result))
      // 如果加上这批记录会超过限制，只取需要的部分
      const remainingSpace = maxRecords - allRecords.length;
      Output.log(result.records.length,remainingSpace);
      if (result.records.length > remainingSpace) {
        allRecords.push(...result.records.slice(0, remainingSpace));
        hasMore = false; // 达到限制后停止获取更多记录
      } else {
        allRecords.push(...result.records);
        Output.log(allRecords)
        hasMore = result.hasMore;
        cursor = result.cursor;
      }
    }

    // 如果记录数超过限制，提示用户
    if (!hasMore && allRecords.length === maxRecords) {
      Output.log(`注意：表格记录数超过${maxRecords}条，仅处理前${maxRecords}条记录。`);
    }
    
    // 用于存储需要更新的记录
    const updates = [];
    
    // 按标识字段分组记录
    const groups = {};
    for (const record of allRecords) {
      const key = JSON.stringify(
        idFields.map(field => record.getCellValue(field))
      );
      
      if (!groups[key]) {
        groups[key] = [];
      }
      groups[key].push(record);
    }
    
    // 处理每个分组
    for (const [, records] of Object.entries(groups)) {
      if (records.length === 1) {
        // 非重复记录，确保标记字段为空
        updates.push({
          id: records[0].getId(),
          fields: {
            [duplicateFlagFieldId]: ''
          }
        });
      } else {
        // 重复记录，根据标记方式进行标记
        let recordsToMark = [...records];
        
        if (markType === '首项不标记') {
          // 按比较字段排序，不标记第一项
          if (comparisonField) {
            recordsToMark.sort((a, b) => {
              const valueA = a.getCellValue(comparisonField.getName());
              const valueB = b.getCellValue(comparisonField.getName());
              if (valueA < valueB) return -1;
              if (valueA > valueB) return 1;
              return 0;
            });
          }
          recordsToMark = recordsToMark.slice(1);
        } else if (markType === '末项不标记') {
          // 按比较字段排序，不标记最后一项
          if (comparisonField) {
            recordsToMark.sort((a, b) => {
              const valueA = a.getCellValue(comparisonField.getName());
              const valueB = b.getCellValue(comparisonField.getName());
              if (valueA < valueB) return -1;
              if (valueA > valueB) return 1;
              return 0;
            });
          }
          recordsToMark = recordsToMark.slice(0, -1);
        }
        
        // 标记需要标记的记录
        for (const record of recordsToMark) {
          updates.push({
            id: record.getId(),
            fields: {
              [duplicateFlagFieldId]: '重复项'
            }
          });
        }
        
        // 对于未标记的记录，确保标记字段为空
        const unmarkedRecords = records.filter(record => !recordsToMark.includes(record));
        for (const record of unmarkedRecords) {
          updates.push({
            id: record.getId(),
            fields: {
              [duplicateFlagFieldId]: ''
            }
          });
        }
      }
    }
    
    // 更新所有记录的重复标记字段
    while (updates.length > 0) {
      const batch = updates.slice(0, maxRecordsPerCall);
      await sheet.updateRecordsAsync(batch);
      updates.splice(0, maxRecordsPerCall);
    }
    
    Output.log(`标记方式 ${markType} 共处理了 ${allRecords.length} 条记录。`);
  } catch (error) {
    if (error instanceof Error) {
      Output.error(`执行过程中发生错误: ${error.message}`);
    } else {
      Output.error(`执行过程中发生未知错误`);
    }
  }
}

await main();